package cn.ckx.coding.common.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;

/**
 * json 工具类
 * 
 * @author kunxin.cai
 */
@Slf4j
public class JsonUtil extends ObjectMapper {

    private static final JsonUtil JSON_MAPPER = new JsonUtil();

    private JsonUtil(){
        super.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        
        //允许单引号
        super.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

        //忽略在JSON字符串中存在,但Java对象实际没有的属性
        //null值不序列化
        this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        this.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        this.setTimeZone(TimeZone.getDefault());
        this.registerModules(new JavaTimeModule());
    }

    public static JsonUtil getJsonUtil(){
        return JSON_MAPPER;
    }

    public static String toJson(Object obj){
        try {
            return JSON_MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            log.error("json 转换异常 json:{}", obj, e);
            throw new RuntimeException(String.format("json转换异常 Class:%s", obj.getClass()), e);
        }
    }

    public static <T> T toObject(String json, Class<T> clazz) {
        try {
            return JSON_MAPPER.readValue(json, clazz);
        } catch (IOException e) {
            throw new RuntimeException(String.format("json转换异常 json:%s", json), e);
        }
    }

    public static <T> List<T> toList(String json, Class<T> clazz){
        try {
            return JSON_MAPPER.readValue(json, JSON_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, clazz));
        } catch (IOException e) {
            throw new RuntimeException(String.format("json转换异常 json:%s clazz:%s", json, clazz.getName()), e);
        }
    }

    public static JsonNode toNode(String json) {
        try {
            return JSON_MAPPER.readTree(json);
        } catch (IOException e) {
            throw new RuntimeException(String.format("json转换异常 json:%s", json), e);
        }
    }

    public static <T> T toObject(String json, JavaType javaType) {
        try {
            return JSON_MAPPER.readValue(json, javaType);
        } catch (IOException e) {
            throw new RuntimeException(String.format("json转换异常 json:%s javaType:%s", json, javaType.getTypeName()), e);
        }
    }

}
